<?php

namespace app\api\controller\v27;

use app\api\controller\v2\Auth;
use app\common\cachemodel\acquired_astro\AppAcquiredAstroTestRecord;
use app\common\cachemodel\AppConfig;
use app\common\cachemodel\Fortune;
use app\common\cachemodel\Goods;
use app\common\cachemodel\live\LiveOrderData;
use app\common\cachemodel\lucky\AppLuckyTaskRecord;
use app\common\cachemodel\NatalReport;
use app\common\cachemodel\Orders as OrdersCacheModel;
use app\common\cachemodel\OrdersGoods;
use app\common\cachemodel\OrdersLib;
use app\common\cachemodel\Recode;
use app\common\cachemodel\UserCoupon;
use app\common\cachemodel\ZhunleUserAccountRecord;
use app\common\cachemodel\zl1_relation\Zl1RelationAnalysisFitYou;
use app\common\cachemodel\zl1_relation\Zl1RelationAnalysisIdea;
use app\common\cachemodel\zl1_relation\Zl1RelationAnalysisReport;
use app\common\cachemodel\zl3\Zl3FortuneYearAnalysis;
use app\common\cachemodel\zl4\Zl4HoroscopeGoodTime;
use app\common\cachemodel\zl4\Zl4HoroscopeGoodTimeTemp;
use app\common\cachemodel\zl4\Zl4HoroscopeReport;
use app\common\cachemodel\zl6\Zl6MeditationUnlockData;
use app\common\cachemodel\zl7\Zl7AiAnswerNumData;
use app\common\cachemodel\ZlActivePrizeNumIncRecord;
use app\common\cachemodel\zlcr2\Zlcr2UserQuestion;
use app\common\cachemodel\ZlcrCustomReportGoods;
use app\common\cachemodel\ZlcrCustomReportQuestion;
use app\common\cachemodel\ZlcrCustomReportQuestionInfo;
use app\common\cachemodel\ZlSynastryReport;
use app\common\cachemodel\ZlTarotRecords;
use app\common\lib\exception\ApiException;
use app\common\lib\PushQueue;
use app\common\lib\Util;
use app\common\pay\Ali;
use app\common\pay\Weixin;
use Exception;
use think\Cache;
use think\Db;
use think\Log;
use think\response\Json;

/**
 * @version 2.7.0 订单控制器
 * Class Orders
 * @package app\api\controller\v22
 */
class Orders extends Auth
{
    public $msg;

    /**
     * 接口，获取订单详情
     * @throws Exception
     */
    public function read()
    {
        $this->msg = '';
        $order_id = input('param.order_id', '');
        if (!$order_id)
        {
            return show(config('code.error'), '未知的订单');
        }
        $ordersCacheModel = new OrdersCacheModel();
        $orders = current($ordersCacheModel->batchGetInfo([$order_id]));
        if ($orders)
        {
            if ($orders['uid'] != $this->user['id'])
            {
                return show(config('code.error'), '订单不存在');
            }
            try
            {
                $info = $this->read_data_format($orders);

                $res = [
                    'status' => $info['status'],
                    'status_des' => $info['status_des'],
                    'order_icon' => $info['order_icon'],
                    'des' => $info['des'],
                    'time_remaining' => $info['time_remaining'],
                    'total_amount' => sprintf('%.2f', $info['total_amount']),// 以分为单位的,
                    'recode_data' => $info['recode_data'] ?? null,
                    'goods_data' => $info['goods_data'],
                    'rectification_data' => $info['rectification_data'] ?? null,
                    'active_data' => $info['active_data'] ?? null,
                    'note_tips' => $info['note_tips'] ?? '',
                    'rid' => $info['rid'] ?? 0,
                    'trade_type' => $info['trade_type'],
                    'is_display_recommend_data' => $info['is_display_recommend_data'],
                    'order_id' => $info['order_id'],
                    'return_data' => $info['return_data'] ?? null,
                    'order_data' => $info['order_data'],
                    'order_btn' => $info['order_btn'],
                    'coupon_data' => $info['coupon_data'],
                    'coin_num' => $info['coin_num'] ?? 0,
                    'pwd_status' => $info['pwd_status'] ?? 0,
                ];
            }
            catch (\Exception $e)
            {
                Log::write('订单详情异常：' . $e->getMessage() . '错误文件和行数：' . $e->getFile() . ':' . $e->getLine(), 'error', true);

                return show(config('code.error'), '服务异常，请稍后重试');
            }

            $luckyToastData = Cache::get('lucky_other_task:' . $order_id, false);
            if ($luckyToastData)
            {   // 幸运星 可领取增加提醒
                $res['lucky_toast'] = $luckyToastData;
                Cache::rm('lucky_other_task:' . $order_id);
            }

            return show(config('code.success'), '获取成功', $res);
        }

        return show(config('code.error'), '订单不存在');
    }

    /**
     * 组合订单详情数据格式
     * @param $orders_details
     * @return array
     * @throws Exception
     */
    private function read_data_format($orders_details)
    {
        $ordersCacheModel = new OrdersCacheModel();
        $recodeModel = new Recode();
        $ordersCacheModel->ordersDetail2($orders_details);//订单信息
        $orders_details['order_btn'] = $ordersCacheModel->getDetailOrderBtn($orders_details);//订单按钮
        //重组购买的商品信息
        switch ($orders_details['order_type'])
        {
            case 1://生时矫正
                $ordersCacheModel->RecRead2($orders_details);
                break;
            case 2://日运
            case 3://月运
            case 4://年运
                $ordersCacheModel->FortuneRead2($orders_details);
                break;
            case 5://地图
                $ordersCacheModel->MapRead2($orders_details);
                break;
            case 6 ://教学视频
                $ordersCacheModel->VideoRead2($orders_details);
                break;
            case 7://本命预测
                $ordersCacheModel->MapRead2($orders_details);
                break;
            case 8://会员
                $ordersCacheModel->VipRead2($orders_details);
                break;
            case 15://定制报告
                $customReport = $ordersCacheModel->CustomReport($orders_details);
                $customReport['goods_data']['type'] = 15;
                $orders_details['goods'] = [$customReport['goods_data']['id'] => $customReport['goods_data']];
                //重组订单拓展信息
                $ordersCacheModel->orderGoodsActive($orders_details);
                $orders_details['qid'] = $customReport['question_data']['id'];
                $orders_details['qstatus'] = $customReport['question_data']['status'];
                //获取档案信息
                foreach ($customReport['recode_data'] as $recode)
                {
                    if (!$recode)
                    {
                        continue;
                    }
                    $orders_details['rid'] = $recode['id'];
                    $rname = $recode['name'];
                    $orders_details['recode_data']['info'][] = $recodeModel->recodeInfoFormat($recode);
                    //获取档案信息
                    if ($customReport['question_data']['is_merge'])
                    {
                        $orders_details['recode_data']['des'] = '全部档案';
                    } else
                    {
                        $orders_details['recode_data']['des'] = current($customReport['recode_data'])['name'];
                    }
                }
                $targetInfo = $this->getTargetLink($orders_details);
                array_walk($orders_details['goods_data'], static function (&$v, $k, $p)
                {
                    $v = array_merge($v, $p);
                }, ['target' => $targetInfo['target'], 'link' => $targetInfo['link'], 'rname' => $rname ?? '']);
                if ($orders_details['status'] == 1 && $customReport['question_data']['status_link']['type'] == 2)
                {
                    // $orders_details['note_tips'] = $customReport['question_data']['status_link']['order_des'];
                    $orders_details['note_tips'] = '注：18:00点前的提问可在6小时内得到回复，18:00—次日08:00之间订单将在次日08:00开始计时';
                }
                if ((int)$orders_details['status'] === 1)
                {
                    $orders_details['des'] = '占星师接单后，6小时内得到回复';
                }
                foreach ($customReport['recode_data'] as $recodeItem)
                {
                    if (!$recodeItem['status'])
                    {
                        $orders_details['order_btn'] = Util::orderBtnReset($orders_details['order_btn']);
                        continue;
                    }
                }
                break;
            case 16://todo 塔罗暂未上线
                return $orders_details;
            case 17://合盘报告
                $ordersCacheModel->SynastryReport2($orders_details);
                break;
            case 18://心理测试
                $detail = $ordersCacheModel->MentalTestDetail($orders_details);
                $detail['type'] = 18;
                $orders_details['goods'] = [$detail['id'] => $detail];
                //重组订单拓展信息
                $ordersCacheModel->orderGoodsActive($orders_details);

                $targetInfo = $this->getTargetLink($orders_details);
                array_walk($orders_details['goods_data'], static function (&$v, $k, $p)
                {
                    $v = array_merge($v, $p);
                }, ['target' => $targetInfo['target'], 'link' => $targetInfo['link'], 'rname' => $rname ?? '']);
                break;
            case 19://直播看盘解答
            case 20://直播看盘解答
            case 21://直播看盘解答
                $ordersCacheModel->getAnswerInfo($orders_details);
                break;
            case 22://问答
                $ordersCacheModel->getQuestionInfo($orders_details);
                break;
            case 23:
                $ordersCacheModel->getRelationFitInfo($orders_details);
                break;
            case 24:
                $ordersCacheModel->getRelationIdeaInfo($orders_details);
                break;
            case 25:
            case 26:
                $ordersCacheModel->getRelationFollowInfo($orders_details);
                break;
            case 27://年运拓展
                $ordersCacheModel->getYearLife($orders_details);
                if ((int)$orders_details['gid'] === 91)
                {
                    $orders_details['order_data'][] = [
                        'name' => '开通内容',
                        'value' => $orders_details['des2'],
                        'is_copy' => 0
                    ];
                }
                break;
            case 28://八字
                $ordersCacheModel->getBazi($orders_details);
                if (Goods::isBaziJsjr(28, $orders_details['gid']))
                {
                    $orders_details['order_data'][] = [
                        'name' => '开通内容',
                        'value' => $orders_details['des2'],
                        'is_copy' => 0
                    ];
                }
                break;
            case 29://冥想
                $ordersCacheModel->getMeditation($orders_details);
                break;
            case 30://AI解答(骰子塔罗)
            case 31:
                $ordersCacheModel->getAiAnswer($orders_details);
                $orders_details['order_data'][] = [
                    'name' => '开通内容',
                    'value' => 'AI解问题',
                    'is_copy' => 0
                ];
                break;
            case 32:
                $ordersCacheModel->getAcquiredAstro($orders_details);
                $orders_details['order_data'][] = [
                    'name' => '开通内容',
                    'value' => '后天星座',
                    'is_copy' => 0
                ];
                break;
            case 34://疗愈室充电时长
                $ordersCacheModel->getAiVoice($orders_details);
                $orders_details['order_data'][] = [
                    'name' => '开通内容',
                    'value' => 'AI疗愈',
                    'is_copy' => 0
                ];
                break;
            case 35://起名评分
                $ordersCacheModel->getNameAnalyzeRecord($orders_details);
                break;
        }
        return $orders_details;
    }

    /**
     * 获取订单跳转地址
     * @param $orders_details
     * @return array
     * @throws Exception
     */
    private function getTargetLink($orders_details)
    {
        if ($orders_details['is_skip'])
        {
            $ordersModel = new OrdersCacheModel();
            $linkInfo = $ordersModel->orderTypeLink($orders_details);
            $info['target'] = $linkInfo['target'];
            $info['link'] = $linkInfo['link'];
        } else
        {
            $info['target'] = 'local';
            $info['link'] = 'empty';
        }
        return $info;
    }

    /**
     * 接口，下单
     * order_type 1=>校准生辰,2=>日运,3=>月运,4=>年运,5=>幸运之城,6=>教学视频,7=>本命预测,8=>vip会员
     * order_id 01=>校准生辰 02=>运势 03=>幸运之城，04=>教学视频，05=>本命预测
     * @return Json
     * @throws Exception
     */
    public function pay_unlock()
    {
        $this->msg = '';
        $param['trade_type'] = input('param.trade_type/d', 0);
        $param['order_type'] = input('param.order_type/d', 0);
        $param['gids'] = input('param.gids/s', '');
        $param['param'] = input('param.param', '');
        $param['openid'] = input('param.openid/s', '');
        if ($param['order_type'] === 8 && Util::checkAppVersion('2.10.5') === '小')
        {
            $subs = (new AppConfig())->configInfo('subs');
            if ((int)$subs['disabled_buy_vip'] === 1)
            {
                return show(201, '该版本暂不支持会员付费，请下载新版本准了APP购买会员');
            }
        }
        if ($param['order_type'] === 15)
        {
            $res = $this->checkCustomReportParam($param);
            if ($res)
            {
                return show(config('code.success'), $res['msg'], ['pop' => $res['pop']]);
            }
        }
        OrdersLib::pay_order_param_format2($this, $param);
        //生成订单数据并下单
        $arr = $this->SaveOrder($param);
        if (isset($arr['status']) && $arr['status'] === false)
        {
            return show(config('code.error'), '下单失败', $arr['data']);
        }
//        $distinctId = $this->request->header('distinct-id', '');
//        if ($distinctId)
//        {
//            #神策打点 确认订单打点
//            (new \app\common\service\Orders())->getSensorsTrackData($arr['data']['order_id'], 'buy_confirm');
//        }

        return show(config('code.success'), '下单成功', $arr['data']);
    }

    /**
     * 检测定制报告请求参数
     * @param $param
     * @return array
     * @throws Exception
     */
    private function checkCustomReportParam(&$param)
    {
        //定制报告检测固定问题今日已购买数量
        $customModel = new ZlcrCustomReportGoods();
        $reportNum = $customModel->getGoodsIndexNum();
        if ($reportNum['switch'] && !$reportNum['num'])
        {
            $pop = [
                'tips' => "公测阶段每日限量，今日已无购买名额\n请明日再试",
                'title' => '非常抱歉',
                'type' => 1
            ];
            return [
                'msg' => '商品限量',
                'pop' => $pop
            ];
        }

        $paramTmp = json_decode($param['param'], true);
        $param['supplement_info'] = '';
        $param['abnormal_supplement_info'] = '';
        if (!empty($paramTmp['supplement']))
        {
            ksort($paramTmp['supplement']);//对补充问题进行升序排序
            $res = (new ZlcrCustomReportQuestionInfo())->checkSupplementQuestion($this->user['id'], $paramTmp['supplement']);
            $param['supplement_info'] = $res['supplement_info'];
            $param['abnormal_supplement_info'] = $res['abnormal_supplement_info'] ?: '';
            if ($param['abnormal_supplement_info'])
            {
                //处理违规补充问题
                $customReportInfo = (new AppConfig())->configInfo('custom_report');
                if (isset($customReportInfo['supplement_question']) && $customReportInfo['supplement_question'] == 2)
                {
                    $pop = [
                        'tips' => "您的补充问题描述检测到异常！请去修改，否则订单无法完成",
                        'title' => '',
                        'type' => 2
                    ];
                    return [
                        'msg' => '问题异常',
                        'pop' => $pop
                    ];
                }
            }
        }
        Cache::set($customModel->custom_report_goods_index_num_cache . date('Ymd'), $reportNum['num'] - 1, 86400);
        return [];
    }

    /**
     * 生成订单，并下单
     * @param $param ['order_type','trade_type','rid','cid','reid','gids','goods_info','price'，'start_time','out_trade_no','account','extend','pay_des','openid']
     * @return array|bool|Json
     * @throws Exception
     */
    private function SaveOrder($param)
    {
        $CouponModel = new UserCoupon();
        $orderModel = new OrdersCacheModel();
        $orderUpdate = [];
        $gid = (int)current($param['gids']);
        Db::startTrans();
        try
        {
            //若是运势，则添加运势中间表数据
            if (in_array($param['order_type'], [2, 3, 4], false))
            {
                $middle_res = $this->pay_fortune($param['rid'], $param['start_time'], $param['order_type']);
                if (!$middle_res)
                {
                    throw new ApiException('下单失败,请重新操作');
                }
            } elseif ($param['order_type'] === 22)
            {
                if (!$param['history_id'])
                {
                    throw new ApiException('下单失败,请重新操作');
                }
                $res = (new Zlcr2UserQuestion())->getQuestionType($gid);
                $question = (new Zlcr2UserQuestion())->getInfoById($param['history_id'], ['uid', 'question_type', 'status', 'order_num']);
                if (!$question)
                {
                    throw new ApiException('下单失败,请重新操作');
                }
                //非蹭看订单验证uid,驗證用戶信息及問題類型信息
                if ($res['type'] !== 1 && $question['uid'] != $this->user['id'])
                {
                    throw new ApiException('下单失败,请重新操作');
                }
                //追问订单处理
                if ($res['type'] === 2)
                {
                    //待追问
                    if ($question['status'] == 5 && $res['sec'] !== (int)$question['question_type'])
                    {
                        throw new ApiException('下单失败,请重新操作');
                    }
                    //追问订单两分钟关闭
                    $delayTime = 120;
                }
                //问答订单需要验证问题信息,非待下单问题不能再次下单
                if ($res['type'] === 3 && $question['status'])
                {
                    throw new ApiException('下单失败,请重新操作');
                }
                $middle_res = $param['history_id'];
            }
            if ($param['order_type'] === 16 && isset($param['order_num']) && $param['order_num'])
            {
                $param['out_trade_no'] = $param['order_num'];
                $orderUpdate = [
                    'gid' => $gid,
                    'trade_type' => $param['trade_type'],
                    'total_amount' => $param['price'],
                    'status' => 0,
                    'account' => $param['account'],
                    'extend' => $param['extend']
                ];
                $oid = $param['oid'];
            } else
            {
                //生成订单数据
                $insert = [
                    'order_type' => $param['order_type'],
                    'uid' => $this->user['id'],
                    'gid' => $gid,
                    'order_id' => $param['out_trade_no'],
                    'reid' => $param['reid'],
                    'fid' => $middle_res ?? 0,
                    'trade_type' => $param['trade_type'],
                    'total_amount' => $param['price'],
                    'create_time' => $this->request->time(),
                    'status' => 0,
                    'env_type' => $param['env_type'] ?? 1,
                    'account' => $param['account'],
                    'extend' => $param['extend']
                ];
                // 生成订单到数据库
                $oid = $orderModel->SaveData($insert);
                if ($oid === false)
                {
                    throw new ApiException('下单失败,请重新操作');
                }

                //添加中间表数据
                if ($param['rid'])
                {
                    $middle_res = $this->insertMiddle($param['rid'], $param['gids'], $oid);
                    if ($middle_res === false)
                    {
                        throw new ApiException('下单失败,请重新操作');
                    }
                }
            }
            switch ($param['order_type'])
            {
                case 15://添加定制报告问题记录
                    (new ZlcrCustomReportQuestion())->addCustomReport($insert, $param);
                    break;
                case 16: //塔罗记录更新订单编号数据
                    (new ZlTarotRecords())->updateData($param['history_id'], ['order_num' => $param['out_trade_no']]);
                    break;
                case 22: //问答处理
                    $historyId = (new Zlcr2UserQuestion())->orderQuestion(1, $param['out_trade_no']);
                    if ($historyId)
                    {
                        $orderUpdate['extend']['history']['id'] = $historyId;
                    }
                    break;
            }
            //修改优惠券状态为已锁定
            if ($param['cid'])
            {
                $res = $CouponModel->use_return($this->user['id'], $param['cid'], ['status' => 4, 'oid' => $oid, 'update_time' => $this->request->time()]);
                if ($res === false)
                {
                    throw new ApiException($CouponModel->getError());
                }
            }
            //检测订单关闭入队
            PushQueue::CloseOrder($param['out_trade_no'], $delayTime ?? 0);

            if ($orderUpdate)
            {
                if (isset($orderUpdate['extend']))
                {
                    $orderUpdate['extend'] = json_encode($orderUpdate['extend'], true);
                }
                $updateRes = $orderModel->UpdateData($param['out_trade_no'], $orderUpdate, 0);
                if (!$updateRes)
                {
                    throw new ApiException('下单失败,请重新操作');
                }
            }
            Db::commit();
        }
        catch (Exception $e)
        {
            Db::rollback();
            Log::write('入库失败信息：' . $e->getMessage() . '【' . $e->getFile() . $e->getLine() . '】', 'error');
            throw new ApiException('下单失败,请重新操作');
        }

        //支付订单
        $arr = OrdersLib::unifyPayOrder([
            'oid' => $oid,
            'trade_type' => $param['trade_type'],
            'total_amount' => $param['price'],
            'pay_des' => $param['pay_des'],
            'order_id' => $param['out_trade_no'],
            'openid' => $param['openid'],
            'callback_url' => '',
            'order_type' => $param['order_type']
        ], 1);
        if ($this->headers['app-type'] === 'ios')
        {
            $new_gid = [];
            foreach ($param['gids'] as $gid)
            {
                $new_gid[] = 'apple_pay_' . $gid;
            }
            $skuId = implode(',', $new_gid);
            $arr['data']['skuId'] = $skuId;
        }

        $arr['data']['oid'] = $oid;
        $arr['data']['order_id'] = $param['out_trade_no'];
        $arr['data']['uuid'] = Util::encryptUuid($param['out_trade_no']);
        $arr['data']['trade_type'] = $param['trade_type'];
        $arr['data']['total_amount'] = $param['price'];
        return $arr;
    }

    /**
     * 运势下单
     * @param int $rid
     * @param int $start_time
     * @param int $order_type
     * @return bool|int|string
     */
    private function pay_fortune($rid, $start_time, $order_type)
    {
        $arr = [
            'type' => $order_type - 1,
            'rids' => $rid,
            'time' => $start_time,
            'create_time' => $this->request->time(),
        ];
        return (new Fortune())->insertGetId($arr); //每日运势id
    }

    /**
     * 添加中间表数据
     * @param $rid
     * @param $gids
     * @param $oid
     * @return bool
     */
    private function insertMiddle($rid, $gids, $oid)
    {
        try
        {
            $array = [];
            foreach ($gids as $k => $v)
            {
                $array[] = [
                    'gid' => $v,
                    'oid' => $oid,
                    'rid' => $rid
                ];
            }
            //中间表
            (new OrdersGoods())->insertAll($array);
        }
        catch (\Exception $e)
        {
            return false;
        }
        return true;
    }


    /**
     * 接口，免费下单
     * @throws ApiException
     * @throws Exception
     */
    public function free_pay_unlock()
    {
        $param['trade_type'] = input('param.trade_type/d', 0);
        $param['order_type'] = input('param.order_type/d', 0);
        $param['gids'] = input('param.gids/s', '');
        $param['param'] = input('param.param', '');
        $param['password'] = input('param.password', '');
        $param['openid'] = input('param.openid/s', '');
        OrdersLib::pay_order_param_format2($this, $param, true);
        if ($param['price'] <= 0)
        {
            //使用免费券或支付金额小于0
            $data = $this->SaveFreeOrder($param);
            $distinctId = $this->request->header('distinct-id', '');
            if ($distinctId)
            {
                #神策打点 确认订单
                (new \app\common\service\Orders())->getSensorsTrackData($data, 'buy_confirm');
                #神策打点 免费支付成功
                (new \app\common\service\Orders())->getSensorsTrackData($data, 'buy_success');
            }
            return show(config('code.success'), '下单成功', ['order_id' => $data]);
        }
        return show(config('code.error'), '下单金额有误');
    }

    /**
     * 生成订单数据并入队
     * @param $param [cid,rid,start_time,order_type,gids,out_trade_no,reid,extend,goods_info]
     * @return string
     * @throws ApiException
     * @throws Exception
     */
    private function SaveFreeOrder($param)
    {
        $middle_res = true;
        $CouponModel = new UserCoupon();
        $now_time = $this->request->time();
        $gid = (int)(current($param['gids']));
        //订单状态
        $status = OrdersLib::getOrderStatus($param['gids'], $param['order_type']);
        Db::startTrans();
        try
        {
            (new Recode())->UpdateData($this->user['id'], $param['rid'], [], 1);//or_day生成
            //若是运势，则添加运势中间表数据
            if (in_array($param['order_type'], [2, 3, 4], true))
            {
                $middle_res = $this->pay_fortune($param['rid'], $param['start_time'], $param['order_type']);
            }
            if (!$middle_res)
            {
                throw new ApiException('下单失败,请重新操作');
            }
            //生成订单数据
            $insert = [
                'order_type' => $param['order_type'],
                'uid' => $this->user['id'],
                'gid' => $gid,
                'order_id' => $param['out_trade_no'],
                'reid' => $param['reid'],
                'fid' => $middle_res === true ? 0 : $middle_res,
                'trade_type' => $param['trade_type'],
                'total_amount' => 0,
                'env_type' => $param['env_type'] ?? 1,
                'create_time' => $now_time,
                'update_time' => $now_time,
                'pay_time' => $now_time,
                'status' => $status,
                'account' => 0,
                'extend' => $param['extend']
            ];
            // 生成订单到数据库
            $OrdersCacheModel = new OrdersCacheModel();
            //生成订单数据
            $oid = $OrdersCacheModel->SaveData($insert);
            if ($oid === false)
            {
                throw new ApiException('下单失败,请重新操作');
            }
            //增加直播间数据统计记录
            $orderTmp = [];
            foreach ($param['gids'] as $tmpGid)
            {
                $insert['gids'] = $tmpGid;
                $insert['rid'] = $param['rid'];
                $orderTmp[] = $insert;
            }
            (new LiveOrderData())->saveData($orderTmp);
            //添加中间表数据
            if ($param['rid'])
            {
                $middle_res = $this->insertMiddle($param['rid'], $param['gids'], $oid);
                if ($middle_res === false)
                {
                    throw new ApiException('下单失败,请重新操作');
                }
            }
            $extend = json_decode($param['extend'], true);
            //商品购买人数自增,教学视频和本命报告根据课程进行缓存数据
            if (in_array($param['order_type'], [6, 7], true))
            {
                $OrdersCacheModel->SaveTotalPrepaidOrder($param['order_type'], $gid);
            } elseif ($param['order_type'] === 17)
            {   // 合盘报告 根据gid自增 和gid与关系ID【relation_id】新增 维护两个缓存
                $OrdersCacheModel->SaveTotalPrepaidOrder($param['order_type'], $extend['synastry_report']['srid']); // 根据srid自增
                $OrdersCacheModel->SaveTotalPrepaidOrder($param['order_type'], $extend['synastry_report']['srid'], $extend['synastry_report']['relation_id']); // 根据srid与关系ID【relation_id自增
            } else
            {
                $OrdersCacheModel->SaveTotalPrepaidOrder($param['order_type'], 0);
            }

            //修改优惠券状态为已锁定
            if ($param['cid'])
            {
                $res = $CouponModel->use_return($this->user['id'], $param['cid'], ['status' => 1, 'oid' => $oid, 'update_time' => $this->request->time()]);
                if ($res === false)
                {
                    throw new ApiException($CouponModel->getError());
                }
            }

            //生成第三方数据和入队
            switch ($param['order_type'])
            {
                case  1://校准生辰入队
                    $this->RecQueue($param['reid'], $oid, $param['out_trade_no']);
                    break;
                case 3://运势入队
                case 4:
                    $this->FortuneQueue($this->user['id'], $oid);
                    break;
                case 5://地图入队
                    (new PushQueue())->Map($param['out_trade_no']);
                    break;
                case 7://本命预测入队
                    $this->NatalQueue($param['rid'], $param['gids'], $param['out_trade_no']);
                    break;
                case  8://若是vip，更新vip有效期和生效状态
                    $middle_res = $this->pay_vip($insert, $gid);
                    break;
                case 15://定制报告入队
                    $questionModel = new ZlcrCustomReportQuestion();
                    //问题入队
                    $questionModel->orderReportQueue($insert['order_id']);
                    break;
                case  16 : //修改塔罗记录状态
                    $taroId = $extend['history']['id'];
                    (new ZlTarotRecords())->updateData($taroId, ['status' => 1]);
                    break;
                case 17:
                    $this->SynastryQueue($insert, (int)$gid, null);
                    break;
                case  23://适合你的TA
                    //打包解锁特殊处理
                    if ($gid === 87)
                    {
                        $unlock_gids = [84, 85, 86];
                    } else
                    {
                        $unlock_gids = $param['gids'];
                    }
                    (new Zl1RelationAnalysisFitYou())->SaveAndQueue((int)$this->user['id'], (int)$param['rid'], $unlock_gids, $param['out_trade_no']);
                    break;
                case 24://你的理想型
                    $case = $extend['relation_idea_info'];
                    (new Zl1RelationAnalysisIdea())->SaveDataAndQueue(['uid' => $this->user['id'], 'rids' => $case['rids'], 'tag_info' => $case['tag_info'], 'gid' => $gid, 'order_num' => $param['out_trade_no'], 'create_time' => time()]);
                    break;
                case  25://怎么追求TA
                    $rids = $extend['recode_ids'];
                    (new Zl1RelationAnalysisReport())->SaveAndQueue($insert['uid'], 1, $insert['gid'], $insert['order_id'], $rids['rid1'], $rids['rid2']);
                    break;
                case  26://鉴渣神器
                    (new Zl1RelationAnalysisReport())->SaveAndQueue($insert['uid'], 2, $insert['gid'], $insert['order_id'], $insert['rid']);
                    break;
                case  27:
                    $recodeInfo = $extend['recode_info'];
                    if ($insert['gid'] === 91)
                    {
                        //获取人生阶段
                        $insertType = 2;
                        $stateYear = Util::getRecodeStageyear($recodeInfo, $extend['year_life']['start_time']);
                        $stageyear = (int)($stateYear['start_year'] . $stateYear['end_year']);
                        $stage_num = $stateYear['num'];

                    } elseif ($insert['gid'] === 92)
                    {
                        $insertType = 3;
                    }
                    $inserData = [
                        'uid' => $insert['uid'],
                        'rid' => $recodeInfo['id'],
                        'type' => $insertType ?? 0,
                        'hash' => Util::getRecodeHashKey($recodeInfo),
                        'status' => 1,
                        'order_num' => $insert['order_id'],
                        'stageyear' => $stageyear ?? 0,
                        'stage_num' => $stage_num ?? 0,
                        'recode_info' => json_encode($recodeInfo, JSON_UNESCAPED_UNICODE),
                    ];
                    (new Zl3FortuneYearAnalysis())->SaveDataAndQueue($inserData);
                    break;
                case  28:
                    $recodeInfo = (new Recode())->getInfoById($param['rid']);
                    $recodeEncode = json_encode($recodeInfo, JSON_UNESCAPED_UNICODE);
                    if (Goods::isBaziJsjr(28, $insert['gid']))//择时
                    {
                        $nowTime = time();
                        $GoodTimeSimData = (new Zl4HoroscopeGoodTimeTemp())->getInfoById($extend['history']['id']);
                        $data = [
                            'uid' => $insert['uid'],
                            'hash' => $GoodTimeSimData['hash'],
                            'rid1' => $GoodTimeSimData['rid1'],
                            'rid2' => $GoodTimeSimData['rid2'],
                            'tid' => $GoodTimeSimData['tid'],
                            'status' => 2,  // 直接计算成功
                            'order_num' => $insert['order_id'],
                            'start_date' => $GoodTimeSimData['start_date'],
                            'end_date' => $GoodTimeSimData['end_date'],
                            'day_num' => $GoodTimeSimData['day_num'],
                            'unlock_day_num' => $GoodTimeSimData['unlock_day_num'],
                            'unlock_days' => json_encode($GoodTimeSimData['unlock_days'], JSON_UNESCAPED_UNICODE),
                            'content' => json_encode($GoodTimeSimData['content'], JSON_UNESCAPED_UNICODE),
                            'recode_info' => json_encode($GoodTimeSimData['recode_info'], JSON_UNESCAPED_UNICODE),
                            'create_time' => $nowTime,
                            'end_time' => $nowTime,
                        ];
                        (new Zl4HoroscopeGoodTime())->SaveData($insert['uid'], $data);
                    } else
                    {
                        if ($insert['gid'] === 106)//用神
                        {
                            $type = 2;
                            $status = 0;
                        } else if ($insert['gid'] === 107)//72格局
                        {
                            $type = 1;
                            $status = 1;
                        }
                        $data = [
                            'uid' => $insert['uid'],
                            'rid' => $param['rid'],
                            'type' => $type,    // 类型  1=>72格局判定 2=>用神详解
                            'hash' => Util::getRecodeHashKey($recodeInfo),    //  Util::getRecodeHashKey($recode) 调用该方法获取
                            'status' => $status,   // 计算状态  0=>待计算 1=>计算中 2=>计算完成 3=>计算失败      72格局判定 默认入库计算中状态 ｜ 用神详解 默认入库 待计算状态
                            'order_num' => $insert['order_id'],   // 订单编号
                            'recode_info' => $recodeEncode,  // 档案信息  json_encode
                        ];
                        (new Zl4HoroscopeReport())->SaveDataAndQueue($data);
                    }
                    break;
                case 29:
                    $meditation = $extend['meditation'];
                    $mid = array_keys($meditation)[0];
                    (new Zl6MeditationUnlockData())->SaveData($insert['uid'], [
                        'uid' => $insert['uid'],
                        'mid' => $mid,
                        'sign' => $meditation[$mid]['in_sign'],
                        'order_num' => $insert['order_id'],
                        'create_time' => time()
                    ]);
                    break;
                case 30://AI解答(骰子塔罗)
                case 31://AI解答
                    $num = $extend['ai_answer']['num'];
                    (new Zl7AiAnswerNumData())->updateData($insert['uid'], ['ai_num' => ['inc', $num], 'total_num' => ['inc', $num], 'update_time' => $this->request->time()]);
                    break;
                case 32://后天星座
                    $acquiredAstroId = (new AppAcquiredAstroTestRecord())->saveData([
                        'uid' => $insert['uid'],
                        'type' => 2,
                        'status' => 0,
                        'order_num' => $insert['order_id'],
                        'create_time' => time()
                    ]);
                    $extend['acquired_astro']['id'] = $acquiredAstroId;
                    break;
                case 34://todo 疗愈室充电时长
                    break;
                case 35://todo 起名/评分
                    break;
            }
            //更新星力值
            if ($param['order_type'] !== 8)
            {   // VIP订单除外 更新星力值，  VIP星力值已经更新过了，禁止重复更新
                OrdersLib::UpdateVipBoon($insert, $gid, true);
            }
            if ($middle_res == false)
            {
                throw new ApiException('下单失败,请重新操作');
            }
            //塔罗记录更新订单编号数据
            if ($param['order_type'] === 16)
            {
                (new ZlTarotRecords())->updateData($param['history_id'], ['order_num' => $param['out_trade_no']]);
            }

            //更新订单详情缓存
            $OrdersCacheModel->UpdateData($param['out_trade_no'], ['extend' => json_encode($extend, JSON_UNESCAPED_UNICODE)], $status);

            //2.8.5以后幸运星完成其他任务
            $orderVersion = isset($extend['app_info']) ? $extend['app_info']['version'] : '';
            if ($orderVersion)
            {
                if (Util::CheckAppVersion('2.8.5', $orderVersion) !== '小')
                {
                    //其他任务完成
                    $taskInfo = config('lucky_task.order_task');
                    if (isset($taskInfo[$insert['order_type']]) && $gid !== 83)
                    {
                        (new AppLuckyTaskRecord())->setOtherTaskSuccess($insert['uid'], $taskInfo[$insert['order_type']], $insert['order_id']);
                    }
                }
            }

            Db::commit();
        }
        catch (Exception $e)
        {
            Db::rollback();
            Log::write('下单失败:' . $e->getMessage() . "文件信息:[{$e->getFile()} : {$e->getLine()}]");
            throw new ApiException('下单失败,请重新操作');
        }
        // 开盲盒任务判断
        (new ZlActivePrizeNumIncRecord())->goodsTask($this->user['id'], $gid, $param['out_trade_no']);

        return $param['out_trade_no'];
    }

    /**
     * 校准生辰入队
     * @param $reid
     * @param $oid
     * @param $out_trade_no
     * @throws Exception
     */
    private function RecQueue($reid, $oid, $out_trade_no)
    {
        (new PushQueue())->Rectification($this->user, $reid, $oid, $out_trade_no);
    }

    /**
     * 运势入队
     * @param $uid
     * @param $oid
     * @return bool|mixed
     * @throws Exception
     */
    private function FortuneQueue($uid, $oid)
    {
        return (new PushQueue)->Fortune(['uid' => $uid, 'oid' => $oid]);
    }

    /**
     * 本命预测入队加结果数据写入
     * @param int $rid
     * @param array $gids
     * @param string $order_id
     * @throws Exception
     */
    private function NatalQueue($rid, $gids, $order_id)
    {
        $NatalReportModel = new NatalReport();
        $NatalReportModel->SaveQueue($this->user['id'], $rid, $gids, $order_id);
    }

    /**
     * 本命预测入队加结果数据写入
     * @param array $orders
     * @param int $unlock_gid
     * @param null $queueDelay 队列延迟时间
     * @throws Exception
     */
    private function SynastryQueue(array $orders, int $unlock_gid, $queueDelay = null)
    {
        $extend = json_decode($orders['extend'], true);
        (new ZlSynastryReport())->SaveQueue($this->user['id'], $unlock_gid, $extend['synastry_report'], $orders['order_id'], $queueDelay);
    }

    /**
     * 会员下单
     * @param $orders
     * @param $gid
     * @return bool
     */
    private function pay_vip($orders, $gid)
    {
        return OrdersLib::UpdateVipStatus($orders, $gid);
    }

    /**
     * 支付三方查询订单支付状态
     * @return string
     * @throws Exception
     */
    public function orderQuery()
    {
        $orderId = input('order_id', '');
        if (!$orderId)
        {
            return show(config('code.error'), '未知的订单');
        }
        //若当前为校准生辰订单,则将校准生辰历史记录也删除
        $num = substr($orderId, 1, 1);
        if ($num == 7)
        {
            $orders = (new ZhunleUserAccountRecord())->where(['order_id' => $orderId])->column('trade_type,order_id,account', 'id');
        } else
        {
            $orders = (new OrdersCacheModel())->batchGetInfo([$orderId]);
        }
        if (!$orders)
        {
            return show(config('code.error'), '未知的订单');
        }
        $orders = current($orders);
        if ($orders['trade_type'] == 1)
        {
            $res = $this->aliQuery($orders);
        }
        if ($orders['trade_type'] == 2)
        {
            $res = $this->wxQuery($orders);
        }
        if (!empty($res))
        {
            if ($res['status'])
            {
                return show(config('code.success'), '充值成功', ['status' => $res['status']]);
            }

            return show(config('code.success'), '充值失败', ['status' => $res['status']]);
        }
        return show(config('code.error'), '查询异常', ['status' => 0]);
    }

    /**
     * 微信订单查询
     * @param $orders
     * @param string $type wxpay,wxwebpay,wx_mini_astro_pay,wx_mini_astro_h5_pay
     * @return array
     */
    private function wxQuery($orders, $type = 'wxpay')
    {
        $WxPay = new Weixin();
        //查询微信平台该订单支付状态
        $wxpayConfig = \app\common\lib\Orders::getPayConfig('wx', $orders['account']);
        $response = $WxPay->query($orders['order_id'], $wxpayConfig[$type]);
        $data = [
            'msg' => $response['trade_state'],
            'status' => 0
        ];
        if ($response['return_code'] === 'SUCCESS')
        {
            //微信平台订单状态为已支付
            if ($response['result_code'] === 'SUCCESS' && $response['trade_state'] === 'SUCCESS')
            {
                $data = [
                    'msg' => '订单已在微信支付',
                    'status' => 1
                ];
            }
        }
        return $data;
    }

    /**
     * 支付宝订单查询
     * @param $orders
     * @return array
     * @throws Exception
     */
    private function aliQuery($orders)
    {
        $AliPay = new Ali();
        $result = json_decode(json_encode($AliPay->query(['out_trade_no' => $orders['order_id'], 'trade_no' => ''], $orders['account'])), true)['alipay_trade_query_response'];
        $data = [
            'msg' => '订单未支付',
            'status' => 0
        ];
        // 支付宝已经内置验签 支付成功
        if ($result['code'] == '10000')
        {
            $tarde_status = $result['trade_status'];
            //支付宝平台订单状态为已支付
            if ($tarde_status === 'TRADE_SUCCESS')
            {
                $data = [
                    'msg' => '订单已在支付宝支付',
                    'status' => 1
                ];
            }
        } else
        {
            $data = [
                'msg' => $result['sub_msg'],
                'status' => 0
            ];
        }
        return $data;
    }
}
